﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.IO;
using AbpOne.Domain.Configurations;
using AbpOne.Domain.Shared;
using AbpOne.Swagger.Filters;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerUI;


namespace AbpOne.Swagger {
    public static class AbpOneSwaggerExtensions {
        internal class SwaggerApiInfo {
            /// <summary>
            /// URL前缀
            /// </summary>
            public string UrlPrefix { get; set; }

            /// <summary>
            /// 名称
            /// </summary>
            public string Name { get; set; }

            /// <summary>
            /// <see cref="Microsoft.OpenApi.Models.OpenApiInfo"/>
            /// </summary>
            public OpenApiInfo OpenApiInfo { get; set; }
        }

        private const string description = "Blog: http://blog.deali.cn";
        private static string Version => AppSettings.ApiVersion;

        private static readonly List<SwaggerApiInfo> ApiInfos = new List<SwaggerApiInfo>() {
            new SwaggerApiInfo {
                UrlPrefix = Grouping.GroupName_v1,
                Name = "博客前台接口",
                OpenApiInfo = new OpenApiInfo {
                    Version = Version,
                    Title = "AbpOne - 博客前台接口",
                    Description = description
                }
            },
            new SwaggerApiInfo {
                UrlPrefix = Grouping.GroupName_v2,
                Name = "博客后台接口",
                OpenApiInfo = new OpenApiInfo {
                    Version = Version,
                    Title = "AbpOne - 博客后台接口",
                    Description = description
                }
            },
            new SwaggerApiInfo {
                UrlPrefix = Grouping.GroupName_v3,
                Name = "通用公共接口",
                OpenApiInfo = new OpenApiInfo {
                    Version = Version,
                    Title = "阿星Plus - 通用公共接口",
                    Description = description
                }
            },
            new SwaggerApiInfo {
                UrlPrefix = Grouping.GroupName_v4,
                Name = "JWT授权接口",
                OpenApiInfo = new OpenApiInfo {
                    Version = Version,
                    Title = "阿星Plus - JWT授权接口",
                    Description = description
                }
            }
        };

        public static IServiceCollection AddSwagger(this IServiceCollection services) {
            return services.AddSwaggerGen(options => {
                // 遍历并应用Swagger分组信息
                ApiInfos.ForEach(x => { options.SwaggerDoc(x.UrlPrefix, x.OpenApiInfo); });
                
                // Swagger 小绿锁配置
                var security = new OpenApiSecurityScheme
                {
                    Description = "JWT模式授权，请输入 Bearer {Token} 进行身份验证",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                };
                options.AddSecurityDefinition("oauth2", security);
                options.AddSecurityRequirement(new OpenApiSecurityRequirement { { security, new List<string>() } });
                options.OperationFilter<AddResponseHeadersFilter>();
                options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
                options.OperationFilter<SecurityRequirementsOperationFilter>();

                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AbpOne.HttpApi.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AbpOne.Domain.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AbpOne.Application.Contracts.xml"));

                // 应用Controller的API文档描述信息
                options.DocumentFilter<SwaggerDocumentFilter>();
            });
        }

        public static void UseSwaggerUi(this IApplicationBuilder app) {
            app.UseSwaggerUI(options => {
                // 遍历分组信息，生成Json
                ApiInfos.ForEach(x => { options.SwaggerEndpoint($"/swagger/{x.UrlPrefix}/swagger.json", x.Name); });

                // 模型的默认扩展深度，设置为 -1 完全隐藏模型
                options.DefaultModelsExpandDepth(-1);
                // API文档仅展开标记
                options.DocExpansion(DocExpansion.List);
                // API前缀设置为空
                options.RoutePrefix = string.Empty;
                // API页面Title
                options.DocumentTitle = "😍接口文档 - AbpOne⭐⭐⭐";
            });
        }
    }
}